package com.je.core.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.je.core.base.MethodArgument;
import com.je.core.constants.ConstantVars;
import com.je.core.constants.StatusType;
import com.je.core.constants.tree.NodeType;
import com.je.core.dao.PCDaoTemplateImpl;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.core.exception.PlatformException;
import com.je.core.exception.PlatformExceptionEnum;
import com.je.core.mapper.query.Query;
import com.je.core.util.*;
import com.je.core.util.bean.BeanUtils;
import com.je.core.util.bean.DynaBean;
import com.je.develop.vo.FuncInfo;
import com.je.develop.vo.FuncPermVo;
import com.je.develop.vo.FuncQueryStrategy;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.ibatis.extension.plugins.pagination.Page;
import com.je.message.service.PcMessageManager;
import com.je.message.vo.app.UserMsgAppInfo;
import com.je.rbac.model.EndUser;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实现平台基础功能
 *
 * @author wangmm@ketr.com.cn
 * @date 2019/12/6
 */
@Service
public class PlatformManager {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private PCDynaBeanTemplate dynaBeanTemplate;

    @Autowired
    private MetaService metaService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private QueryBuilder queryBuilder;

    @Autowired
    private PcMessageManager pcMessageManager;

    public ConditionsWrapper buildWrapper(MethodArgument param) {

        //功能code，表code
        String funcCode = param.getFuncCode();
        String tableCode = param.getTableCode();
        String queryType = param.getQueryType();

        //获取查询条件
        Query query = param.getQuery();
        query.setFuncId(param.getFuncId());

        //设置是否覆盖功能whereSql
        query.setOverrideFuncWhere("1".equals(param.getParameter("coverJquery")));

        //功能相关配置
        FuncInfo funcInfo = null;
        if (StringUtils.isNotBlank(funcCode)) {
            //获取功能配置
            funcInfo = commonService.functionConfig(funcCode);
            query.setFuncId(funcInfo.getFuncId());

            //是否app请求
            String appId = param.getParameter("__appid__");
            if (StringUtils.isNotBlank(appId)) {
                //查询app功能数据
                List<Map<String, Object>> list = metaService.selectSql(ConditionsWrapper.builder().table("JE_PHONE_FUNC_LOG")
                        .apply("SELECT log.LOG_GNSJ FROM\n")
                        .apply("\t(\n")
                        .apply("\t\tJE_PHONE_FUNC_LOG log INNER JOIN ( SELECT log_code, LOG_APP_ID, MAX(LOG_VERSION + 0) LAST_VERSION FROM JE_PHONE_FUNC_LOG GROUP BY log_code, LOG_APP_ID ) last \n")
                        .apply("    ON last.log_code = log.log_code AND last.LAST_VERSION = log.LOG_VERSION AND last.LOG_APP_ID = log.LOG_APP_ID\n")
                        .apply("\t)\n")
                        .apply("WHERE log.LOG_APP_ID = {0} AND log.LOG_CODE = {1}", appId, funcCode));
                if (list != null && !list.isEmpty()) {
                    String appFuncJson = list.get(0).get("LOG_GNSJ").toString();
                    if (StringUtils.isNotBlank(appFuncJson)) {
                        JSONObject appFunc = JSON.parseObject(appFuncJson);

                        query.setAppId(appId);
                        query.setAppFunc(appFunc);

                        query.setFuncPkCode(appFunc.getJSONObject("func").getString("APP_FUNC_PKNAME"));
                        query.setFuncWhereSql(appFunc.getJSONObject("func").getString("APP_FUNC_WHERESQL"));
                        query.setFuncOrderSql(appFunc.getJSONObject("func").getString("APP_FUNC_ORDERSQL"));
                    }
                }
            } else {
                query.setFuncPkCode(funcInfo.getPkCode());
                query.setFuncWhereSql(funcInfo.getWhereSql());
                query.setFuncOrderSql(funcInfo.getOrderSql());
            }

            HttpServletRequest request=param.getRequest();
            //获取查询策略
            if (StringUtils.isNotBlank(query.getStrategyId()) && !"1".equalsIgnoreCase(request.getParameter("disableQuery"))  && StringUtil.isEmpty(appId)) {

                FuncQueryStrategy strategy = null;
                //查找缓存中的查询策略
                if (funcInfo.getStrategies() != null) {
                    List<FuncQueryStrategy> strategiesFilter = funcInfo.getStrategies().stream()
                            .filter(p -> query.getStrategyId().equals(p.getId())).collect(Collectors.toList());
                    if (!strategiesFilter.isEmpty()) {
                        strategy = strategiesFilter.get(0);
                    }
                }
                //数据库查找查询策略
                if (strategy == null) {
                    //7.封装查询策略
                    DynaBean queryStrategy = metaService.selectOne("JE_CORE_QUERYSTRATEGY", ConditionsWrapper.builder().eq("JE_CORE_QUERYSTRATEGY_ID", query.getStrategyId()));
                    if (queryStrategy != null) {
                        strategy = new FuncQueryStrategy(queryStrategy.getStr("JE_CORE_QUERYSTRATEGY_ID"), queryStrategy.getStr("QUERYSTRATEGY_SQL"), queryStrategy.getStr("QUERYSTRATEGY_FGGNSQL"));
                    }
                }
                query.setStrategyBean(strategy);
            }
            //获取功能数据权限
            FuncPermVo funcPermVo = commonService.functionPerm(funcCode);
            query.setFuncPermVo(funcPermVo);
        }

        //设置条件
        ConditionsWrapper wrapper = queryBuilder.buildWrapper(query);
        wrapper.function(funcCode).table(tableCode).selectColumns(param.getQueryColumns());


        //sql类型功能
        if ("sql".equalsIgnoreCase(queryType) && funcInfo != null) {
            // TODO 设置sql功能配置的SQL
            String funcSql = funcInfo.getSql();
            ConditionsWrapper sqlWrapper = ConditionsWrapper.builder();
            String whereSql = wrapper.getSql();
            sqlWrapper.apply("select * from (").apply(QueryBuilder.formatVariable(sqlWrapper, funcSql)).apply(") a")
                    .apply(StringUtils.isNotBlank(whereSql), "where 1=1 and ")
                    .apply(whereSql).putAll(wrapper.getParameter());
            return sqlWrapper;
        }

        return wrapper;

    }

    public Page load(MethodArgument param) {

        //分页对象
        Page page = new Page<>(param.getPage(), param.getLimit());

        //如果是SQL或者存储过程查询
        String queryType = param.getQueryType();
        if (ArrayUtils.contains(new String[]{"procedure", "iditprocedure"}, queryType)
                || ("sql".equalsIgnoreCase(queryType) && StringUtils.isNotEmpty(param.getDatasourceName()) && !"local".equals(param.getDatasourceName()))) {

            //构建排序条件
            String order = dynaBeanTemplate.buildOrderSql(param.getSort(), param.getOrderSql(), param.getUseOrderSql());
            DynaBean dynaBean = param.getDynaBean();

            dynaBean.set(BeanUtils.KEY_ORDER, order);
            if (StringUtil.isNotEmpty(param.getExpandSql())) {
                dynaBean.set(BeanUtils.KEY_WHERE, param.getWhereSql() + param.getExpandSql());
            }
            Map<String, Object> returnObj = dynaBeanTemplate.doLoadOtherData(queryType, param, order);
            //如果需要返回
            if ("1".equals(returnObj.get("returnFlag") + "")) {
                //如果返回成功
                if ("1".equals(returnObj.get("success") + "")) {
                    page.setTotal(Integer.parseInt(returnObj.get("totalCount").toString()));
                    page.setRecords((List<Map>) returnObj.get("rows"));
                } else {
                    String errorMsg = returnObj.get("msg").toString();
                    throw new PlatformException(errorMsg, PlatformExceptionEnum.UNKOWN_ERROR);
                }
            }

            return page;
        }

        String funcId = param.getFuncId();
        String funcCode = param.getFuncCode();

        //构建查询条件
        ConditionsWrapper wrapper = buildWrapper(param);

        List<Map<String, Object>> list = null;

        //sql类型功能
        if ("sql".equalsIgnoreCase(queryType)) {
            list = metaService.selectSql(page, wrapper);
            page.setRecords(list);
        } else {
            //普通功能查询数据
            list = metaService.load(funcCode, page, wrapper);
        }

        //处理批注标记
        if (!list.isEmpty()) {
            if (param.getMark()) {
                EndUser currentUser = SecurityUserHolder.getCurrentUser();
                commonService.buildMarkInfo(list, param.getTableCode(), currentUser, funcId);
            }
            if (param.getPostil()) {
                commonService.buildPostilInfo(list, param.getTableCode(), funcId);
            }
            if (param.getFuncEdit()) {
                EndUser currentUser = SecurityUserHolder.getCurrentUser();
                commonService.buildFuncEditInfo(list, param.getTableCode(), currentUser, funcCode);
            }
        }
        return page;
    }

    public DynaBean doSave(MethodArgument param) {

        //获取新增数据
        DynaBean dynaBean = param.getDynaBean();
        //设置系统字段默认值
        commonService.buildModelCreateInfo(dynaBean);

        // 构建编号
        String codeGenFieldInfo = param.getCodeGenFieldInfo();
        if (StringUtil.isNotEmpty(codeGenFieldInfo)) {
//            if (WebUtils.isSaas()) {
//                EndUser currentUser = SecurityUserHolder.getCurrentUser();
//                commonService.buildCode(codeGenFieldInfo, dynaBean, currentUser.getZhId());
//            } else {
//                commonService.buildCode(codeGenFieldInfo, dynaBean);
//            }

            // SaaS模式租户编号序列在租户间不共享，所以不需要加租户判断
            commonService.buildCode(codeGenFieldInfo, dynaBean);
        }

        //检测是否有主功能,并且外键是否有值,如果有则添加,子功能添加树形,检查是否有ROOT节点操作
        //前端是否刷新左边的树
        Boolean treeLoad = false;
        DynaBean parentTree = dynaBeanTemplate.addParentTree(dynaBean, param.getFuncCode());
        if (parentTree != null) {
            String parentpkValue = parentTree.getStr("__PK_VALUE");
            dynaBean.setStr("SY_PARENT", parentpkValue);
            String uuid = dynaBean.getStr(dynaBean.getStr(BeanUtils.KEY_PK_CODE), "");
            if (StringUtil.isEmpty(uuid)) {
                uuid = JEUUID.uuid() + "";
            }
            dynaBean.set(dynaBean.getStr(BeanUtils.KEY_PK_CODE), uuid);
            dynaBean.setStr("SY_NODETYPE", "LEAF");
            dynaBean.setStr("SY_PARENTPATH", "/" + parentpkValue);
            dynaBean.setStr("SY_LAYER", "1");
            dynaBean.setStr("SY_PATH", "/" + parentpkValue);
            treeLoad = true;
        }
        //处理视图保存
        String funcType = param.getParameter("funcType");
        String funcCode = param.getParameter("funcCode");
        if ("view".equals(funcType) && StringUtil.isNotEmpty(funcCode)) {
            commonService.doViewData(funcCode, dynaBean);
        } else {
            //插入数据
            dynaBean = commonService.doSave(dynaBean);
        }
        //检测子功能是否增加ROOT节点 (子功能多树)
        commonService.doChildrenTree(dynaBean, param.getFuncCode());

        //处理单附件多附件上传
        commonService.doSaveFileMetadata(dynaBean, param.getBatchFilesFields(), param.getUploadableFields(), param.getFuncCode());

        //如果是操作视图，则数据重新查询
        String viewTableCode = param.getParameter("viewTableCode");
        if (StringUtil.isNotEmpty(viewTableCode)) {
            String pkName = BeanUtils.getInstance().getPKeyFieldNames(viewTableCode);
            String pkVal = dynaBean.getStr(pkName);
            if (StringUtil.isNotEmpty(pkVal)) {
                dynaBean = metaService.selectOne(viewTableCode, ConditionsWrapper.builder().eq(dynaBean.getPkCode(), pkVal));
            }
        }
        dynaBean.set("SY_TREELOAD", treeLoad);
        return dynaBean;
    }

    public DynaBean doCopy(MethodArgument param) {
        if (StringUtil.isEmpty(param.getPkValue())) {
            throw new PlatformException("传入原记录主键失败", PlatformExceptionEnum.UNKOWN_ERROR);
        }
        DynaBean dynaBean = param.getDynaBean();
        dynaBean.set(dynaBean.getPkCode(), param.getPkValue());

        //级联复制记录
        DynaBean copy = commonService.doCopy(dynaBean, param.getFuncCode(), param.getCodeGenFieldInfo()
                , param.getUploadableFields());
        return copy;
    }

    public DynaBean doUpdate(MethodArgument param) {

        //支持where条件批量修改
        String batchUpdate = param.getParameter("batchUpdate");
        if ("1".equals(batchUpdate)) {
            return doBatchUpdate(param);
        }

        //构建修改信息
        DynaBean dynaBean = param.getDynaBean();
        commonService.buildModelModifyInfo(dynaBean);
        //处理单附件多附件上传
        commonService.doSaveFileMetadata(dynaBean, param.getBatchFilesFields(), param.getUploadableFields(), param.getFuncCode());
        //处理视图保存
        String funcType = param.getParameter("funcType");
        String funcCode = param.getParameter("funcCode");
        if ("view".equals(funcType) && StringUtil.isNotEmpty(funcCode)) {
            commonService.doViewData(funcCode, dynaBean);
        } else {
            //更新数据
            metaService.update(dynaBean);
        }
        //如果是操作视图，则数据重新查询
        String viewTableCode = param.getParameter("viewTableCode");
        if (StringUtil.isNotEmpty(viewTableCode)) {
            String pkName = BeanUtils.getInstance().getPKeyFieldNames(viewTableCode);
            String pkVal = param.getParameter(pkName);
            if (StringUtil.isNotEmpty(pkVal)) {
                dynaBean = metaService.selectOneByPk(viewTableCode, pkVal);
            }
        }
        if (param.getFuncEdit()) {
            metaService.executeSql("UPDATE JE_CORE_FUNCEDIT set FUNCEDIT_NEW='1' where FUNCEDIT_NEW='0' AND FUNCEDIT_FUNCCODE={0} AND FUNCEDIT_PKVALUE={1}", param.getFuncCode(), dynaBean.getPkValue());
        }
        return dynaBean;
    }

    public DynaBean doBatchUpdate(MethodArgument param) {

        //获取修改内容
        DynaBean dynaBean = param.getDynaBean();

        //获取批量修改条件
        ConditionsWrapper wrapper = param.getQuery().buildWrapper();

        //如果有功能编码则使用功能过滤条件
        if (StringUtils.isNotBlank(param.getFuncCode()) && StringUtils.isNotBlank(param.getFuncId())) {
            wrapper = buildWrapper(param);
        }

        //校验是否有条件
        if (wrapper.getSql().trim().length() == 0) {
            throw new PlatformException("批量修改条件不能为空！", PlatformExceptionEnum.JE_CORE_DYNABEAN_UPDATE_ERROR);
        }

        //批量修改
        metaService.update(dynaBean, wrapper);
        return dynaBean;
    }

    public int doRemove(MethodArgument param) {
        DynaBean dynaBean = param.getDynaBean();
        if (StringUtil.isEmpty(param.getTableCode()) || StringUtil.isEmpty(param.getIds())) {
            throw new PlatformException("参数错误", PlatformExceptionEnum.UNKOWN_ERROR);
        }

        //级联删除子功能
        commonService.removeChild(param.getFuncCode(), param.getTableCode(), dynaBean.getPkCode(), param.getIds(), param.getDoTree());

        //删除该功能下的文档数据和文件
        if (param.getDoTree()) {
            commonService.doRemoveTreeBatchFiles(param.getTableCode(), param.getIds());
        } else {
            commonService.doRemoveBatchFiles(param.getTableCode(), param.getIds());
        }

        //视图级联配置 删除
        String funcType = param.getParameter("funcType");
        String viewConfigInfo = param.getParameter("viewConfigInfo");
        String viewTableCode = param.getParameter("viewTableCode");
        int count = 0;
        if ("view".equals(funcType) && StringUtil.isNotEmpty(viewConfigInfo) && StringUtil.isNotEmpty(viewTableCode)) {
            String mainPkCode = BeanUtils.getInstance().getPKeyFieldNames(viewTableCode);
            count = commonService.doViewDelData(viewConfigInfo, viewTableCode, mainPkCode, param.getIds());
        }
        //删除批注、编辑标记、标记
        String pkCode = BeanUtils.getInstance().getPKeyFieldNames(param.getTableCode());
        commonService.doRemoveData(param.getTableCode(), pkCode, param.getIds(), param.getMark(), param.getFuncEdit(), param.getPostil(), param.getDoTree());
        //删除数据
        String[] idArray = param.getIds().split(",");
        if (param.getDoTree()) {
            ConditionsWrapper wrapper = ConditionsWrapper.builder();
            //删除当前节点及子节点
            wrapper.and(i -> {
                for (String id : idArray) {
                    i.like("SY_PATH", id);
                }
            }).or().in(dynaBean.getPkCode(), idArray);
            if (!"view".equals(funcType)) {
                count = metaService.delete(param.getTableCode(), wrapper);
            }
            return count;
        } else {
            if (!"view".equals(funcType)) {
                count = metaService.delete(param.getTableCode(), ConditionsWrapper.builder().in(dynaBean.getPkCode(), idArray));
            }
            return count;
        }
    }

    public int doEnable(MethodArgument param) {
        if (StringUtil.isNotEmpty(param.getTableCode()) && StringUtil.isNotEmpty(param.getIds())) {
            String pkCode = BeanUtils.getInstance().getPKeyFieldNames(param.getTableCode());
            return metaService.executeSql("update " + param.getTableCode() + " set SY_STATUS = {0} where " + pkCode + " in ({1})", StatusType.ENABLED, param.getIds().split(","));
        } else {
            throw new PlatformException("参数错误", PlatformExceptionEnum.UNKOWN_ERROR);
        }
    }

    public int doDisable(MethodArgument param) {
        if (StringUtil.isNotEmpty(param.getTableCode()) && StringUtil.isNotEmpty(param.getIds())) {
            String pkCode = BeanUtils.getInstance().getPKeyFieldNames(param.getTableCode());
            return metaService.executeSql("update " + param.getTableCode() + " set SY_STATUS = {0} where " + pkCode + " in ({1})", StatusType.DISABLED, param.getIds().split(","));
        } else {
            throw new PlatformException("参数错误", PlatformExceptionEnum.UNKOWN_ERROR);
        }
    }

    public List<Map> doInsertUpdateList(MethodArgument param) {
        DynaBean dynaBean = param.getDynaBean();
        String tableCode = dynaBean.getStr(BeanUtils.KEY_TABLE_CODE);
        String funcType = param.getParameter("funcType");
        String viewConfigInfo = param.getParameter("viewConfigInfo");
        return commonService.doInsertUpdateList(param.getTableCode(), param.getStrData(), funcType, param.getCodeGenFieldInfo(), viewConfigInfo);
    }

    public int doUpdateList(MethodArgument param) {
        String funcType = param.getParameter("funcType");
        String funcCode = param.getParameter("funcCode");
        String updatesels = param.getParameter("updatesels");
        // 构建编号
        String codeGenFieldInfo = param.getCodeGenFieldInfo();
        if (!Strings.isNullOrEmpty(updatesels) && updatesels.equals("0")) {
            return commonService.doUpdateAllList(param.getTableCode(), funcType, funcCode, param.getDynaBean().getValues(), param);
        } else {
            List<DynaBean> updateList = commonService.doUpdateList(param.getTableCode(), param.getStrData(), funcType, funcCode, codeGenFieldInfo);
            return updateList.size();
        }
    }

    public List<DynaBean> doUpdateListAndReturn(MethodArgument param) {
        String funcType = param.getParameter("funcType");
        String funcCode = param.getParameter("funcCode");
        // 构建编号
        String codeGenFieldInfo = param.getCodeGenFieldInfo();
        return commonService.doUpdateList(param.getTableCode(), param.getStrData(), funcType, funcCode, codeGenFieldInfo);
    }

    public int listUpdate(MethodArgument param) {
        DynaBean dynaBean = param.getDynaBean();
        Query query = param.getQuery();
        return metaService.update(dynaBean, queryBuilder.buildWrapper(query));
    }

    public DynaBean getInfoById(MethodArgument param) {
        String pkValue = param.getPkValue();
        DynaBean dynaBean = param.getDynaBean();
        if (StringUtil.isEmpty(pkValue)) {
            pkValue = dynaBean.getPkValue();
        }
        if (StringUtil.isEmpty(pkValue)) {
            return null;
        }
        String tableCode = dynaBean.getStr(BeanUtils.KEY_TABLE_CODE);
        DynaBean selectOne = metaService.selectOneByPk(tableCode, pkValue);
        return selectOne;
    }

    public JSONTreeNode getTree(MethodArgument param) {
        String node = param.getNode();
        if (StringUtils.isEmpty(node)) {
            node = ConstantVars.TREE_ROOT;
        }
        if (StringUtils.isNotEmpty(param.getRootId())) {
            node = param.getRootId();
        }

        DynaBean dynaBean = param.getDynaBean();

        //获取根节点
        if (param.getMoreRoot()) {
            String pkName = dynaBean.getStr(BeanUtils.KEY_PK_CODE);
            //param.getParentSql()
            String j_parent = param.getParameter("j_parent");
            String nodeId = param.getParameter("node");
            Query parent = new Query();
            if (StringUtil.isNotEmpty(j_parent)) {
                parent = Query.build(j_parent);
            }
            DynaBean root;
            if (Strings.isNullOrEmpty(nodeId) || nodeId.equals("ROOT")) {
                root = metaService.selectOne(dynaBean.getStr(BeanUtils.KEY_TABLE_CODE), parent.buildWrapper().eq("SY_NODETYPE", "ROOT"));
            } else {
                DynaBean treeFunc = metaService.selectOne("JE_CORE_FUNCINFO", ConditionsWrapper.builder().eq("FUNCINFO_FUNCCODE", param.getFuncCode()), "FUNCINFO_PKNAME");
                String funcPkName = treeFunc.getStr("FUNCINFO_PKNAME");
                root = metaService.selectOne(dynaBean.getStr(BeanUtils.KEY_TABLE_CODE), parent.buildWrapper().eq(funcPkName, nodeId));
            }
            if (root != null) {
                node = root.getStr(pkName);
            } else {
                return null;
            }
        }
        //查询条件
        Query query = param.getQuery();
        //功能whereSql
        String funcCode = param.getFuncCode();
        if (StringUtils.isNotBlank(funcCode)) {
            //获取功能配置
            FuncInfo funcInfo = commonService.functionConfig(funcCode);

            try {
                if (StringUtil.isNotEmpty(funcInfo.getOtherConfig())) {
                    JSONObject otherConfig = JSON.parseObject(funcInfo.getOtherConfig());
                    if (otherConfig.containsKey("rootId")) {
                        node = QueryBuilder.formatSqlParameter(otherConfig.getString("rootId"));
                    }
                }
            } catch (Exception e) {
                logger.debug(e.getMessage());
            }

            if ("tree".equalsIgnoreCase(funcInfo.getFuncType())) {
                query.setApplySql(QueryBuilder.formatSqlParameter(funcInfo.getWhereSql()));
            }
        }

        String tableCode = param.getTableCode();
        JSONTreeNode template = BeanUtils.getInstance().getTreeTemplate(tableCode);
        //获取树形表数据
        List<JSONTreeNode> jsonTreeNodeList = commonService.loadTreeNodeList(node, tableCode, template, query, null, null);
        //构建ROOT节点
        return commonService.buildJSONNewTree(jsonTreeNodeList, node);
    }

    public List<Map<String, Object>> loadGridTree(MethodArgument param) {

        //功能code，表code
        String funcCode = param.getFuncCode();
        String tableCode = param.getTableCode();

        //获取根节点ID
        String node = param.getNode();
        if (StringUtils.isEmpty(node)) {
            node = ConstantVars.TREE_ROOT;
        }
        if (StringUtils.isNotEmpty(param.getRootId())) {
            node = param.getRootId();
        }
        DynaBean dynaBean = param.getDynaBean();
        if (param.getMoreRoot()) {
            //获取根节点ID
            String pkName = dynaBean.getStr(BeanUtils.KEY_PK_CODE);
            // TODO param.getParentSql() + " and SY_NODETYPE='ROOT'"
            String j_parent = param.getParameter("j_parent");
            Query parent = new Query();
            if (StringUtil.isNotEmpty(j_parent)) {
                parent = Query.build(j_parent);
            }
            DynaBean root = metaService.selectOne(tableCode, parent.buildWrapper().eq("SY_NODETYPE", "ROOT"));
            if (root != null) {
                node = root.getStr(pkName);
            } else {
                return null;
            }
        }
        //构建查询条件
        Query query = param.getQuery();

        //功能相关配置
        if (StringUtils.isNotBlank(funcCode)) {
            //获取功能配置
            FuncInfo funcInfo = commonService.functionConfig(funcCode);
            query.setFuncWhereSql(funcInfo.getOrderSql());
        }
        // TODO ExpandSql
//        if(StringUtil.isNotEmpty(param.getExpandSql())){
//            whereSql+=param.getExpandSql();
//        }

        boolean checked = "1".equals(param.getChecked()) || "true".equalsIgnoreCase(param.getChecked());

        //查询树形数据
        List<Map<String, Object>> records = commonService.loadGridTree(node, tableCode, param.getExcludes(), checked, query);
        if (param.getLimit() != -1) {
            Integer endIndex = param.getStart() + param.getLimit();
            if (endIndex >= records.size()) {
                endIndex = records.size();
            }
            records = records.subList(param.getStart(), endIndex);
        }
        return records;
    }

    public DynaBean treeMove(MethodArgument param) {

        DynaBean dynaBean = param.getDynaBean();
        String tableCode = dynaBean.getStr(BeanUtils.KEY_TABLE_CODE);
        String pkName = dynaBean.getStr(BeanUtils.KEY_PK_CODE);
        DynaBean bean = metaService.selectOneByPk(tableCode, dynaBean.getStr(pkName), pkName + ",SY_TREEORDERINDEX,SY_ORDERINDEX,SY_PATH,SY_PARENTPATH,SY_PARENTPATH,SY_LAYER,SY_PARENT");
        String newParentId = dynaBean.getStr("SY_PARENT");
        String oldParentId = bean.getStr("SY_PARENT");
        String oldPath = bean.getStr("SY_PATH");
        String oldParentPath = bean.getStr("SY_PARENTPATH");
        String oldTreeOrderIndex = bean.getStr("SY_TREEORDERINDEX", "");
        Integer chaLayer = dynaBean.getInt("SY_LAYER", 0) - bean.getInt("SY_LAYER", 0);
        bean.set("SY_PARENT", newParentId);
        bean.set(BeanUtils.KEY_TABLE_CODE, tableCode);
        DynaBean parent = metaService.selectOneByPk(tableCode, newParentId);
        bean.set("SY_PATH", parent.getStr("SY_PATH") + "/" + dynaBean.getStr(pkName));
        bean.set("SY_PARENTPATH", parent.getStr("SY_PATH"));
        bean.set("SY_PARENT", newParentId);
        bean.set("SY_LAYER", parent.getInt("SY_LAYER", 0) + 1);
        if (NodeType.LEAF.equals(parent.getStr("SY_NODETYPE"))) {
            commonService.updateTreePanent4NodeType(tableCode, newParentId);
        }
        bean.set("SY_TREEORDERINDEX", parent.getStr("SY_TREEORDERINDEX"));
        commonService.generateTreeOrderIndex(bean);
        String subStringFunction = DBSqlUtils.getPcDBMethodManager().getSubString();
        String lengthFunction = DBSqlUtils.getPcDBMethodManager().getLength();
        //更新当前节点下所有孩子的路径信息
        if (PCDaoTemplateImpl.DBNAME.equals(ConstantVars.STR_KINGBASEES)) {
            metaService.executeSql("UPDATE " + tableCode + " SET SY_PATH=REPLACE(SY_PATH,'" + oldPath + "','" + bean.getStr("SY_PATH") + "'),SY_PARENTPATH=REPLACE(SY_PARENTPATH,'"
                    + oldParentPath + "','" + bean.getStr("SY_PARENTPATH") + "'),SY_LAYER=(SY_LAYER+"
                    + chaLayer + "),SY_TREEORDERINDEX=(" + subStringFunction + "('" + bean.getStr("SY_TREEORDERINDEX") + "',"
                    + subStringFunction + "(SY_TREEORDERINDEX," + (oldTreeOrderIndex.length() + 1) + ","
                    + lengthFunction + "(SY_TREEORDERINDEX)-" + oldTreeOrderIndex.length() + "))) WHERE SY_PATH LIKE '%"
                    + oldPath + "%' AND " + pkName + "!='" + dynaBean.getStr(pkName) + "' AND "
                    + lengthFunction + "(SY_TREEORDERINDEX)>" + oldTreeOrderIndex.length());
        } else {
            metaService.executeSql("UPDATE " + tableCode + " SET SY_PATH=REPLACE(SY_PATH,'" + oldPath + "','" + bean.getStr("SY_PATH") + "'),SY_PARENTPATH=REPLACE(SY_PARENTPATH,'" + oldParentPath + "','" + bean.getStr("SY_PARENTPATH") + "'),SY_LAYER=(SY_LAYER+" + chaLayer + "),SY_TREEORDERINDEX=('" + bean.getStr("SY_TREEORDERINDEX") + "'+" + subStringFunction + "(SY_TREEORDERINDEX," + (oldTreeOrderIndex.length() + 1) + "," + lengthFunction + "(SY_TREEORDERINDEX)-" + oldTreeOrderIndex.length() + ")) WHERE SY_PATH LIKE '%" + oldPath + "%' AND " + pkName + "!='" + dynaBean.getStr(pkName) + "' AND " + lengthFunction + "(SY_TREEORDERINDEX)>" + oldTreeOrderIndex.length());
        }
        metaService.update(bean);
        commonService.updateTreePanent4NodeType(tableCode, oldParentId);
        return bean;
    }

    public Boolean checkFieldUnique(MethodArgument param) {
        String fieldCode = param.getRequest().getParameter("FIELDCODE");
        DynaBean dynaBean = param.getDynaBean();
        Query query = param.getQuery();
        return commonService.checkFieldUnique(dynaBean, fieldCode, query);
    }

    public DynaBean saveMark(MethodArgument param) {
        DynaBean dynaBean = param.getDynaBean();
        metaService.executeSql("DELETE FROM JE_CORE_MARK WHERE MARK_FUNCID={0} AND MARK_MODELID={1} AND MARK_USERID={2}",
                dynaBean.getStr("MARK_FUNCID"), dynaBean.getStr("MARK_MODELID"), dynaBean.getStr("MARK_USERID"));
        metaService.insert(dynaBean);
        return dynaBean;
    }


    public DynaBean savePostil(MethodArgument param) {
        HttpServletRequest request = param.getRequest();
        DynaBean dynaBean = param.getDynaBean();

        String createUserId = request.getParameter("createUserId");
        String hfrId = dynaBean.getStr("POSTIL_HFRID", "");
        EndUser currentUser = SecurityUserHolder.getCurrentUser();
        String funcName = request.getParameter("funcName");
        commonService.buildModelCreateInfo(dynaBean);
        metaService.insert(dynaBean);
        String title = dynaBean.getStr("SY_CREATEUSERNAME") + "在" + dynaBean.getStr("SY_CREATETIME") + "，功能【" + funcName + "】给您回复了一条内容!";
        StringBuffer context = new StringBuffer();
//		context.append(dynaBean.getStr("SY_CREATEUSERNAME")+"在"+dynaBean.getStr("SY_CREATETIME")+"，功能【"+funcName+"】给您回复了一条内容，");
        context.append(dynaBean.getStr("SY_CREATEUSERNAME") + "在" + dynaBean.getStr("SY_CREATETIME") + "，功能【<a href=\"javascript:void(0)\" onclick=\"javascript:JE.showFunc('" + dynaBean.getStr("POSTIL_FUNCCODE", "") + "',{type:'form',id:'" + dynaBean.getStr("POSTIL_MODELID", "") + "'});\">" + funcName + "</a>】给您回复了一条内容，");
        context.append("内容：" + dynaBean.getStr("POSTIL_PZ") + "，");
        context.append("详细信息请点击,<a href=\"javascript:void(0)\" onclick=\"javascript:JE.CoreUtil.showPostil({funcCode:'" + dynaBean.getStr("POSTIL_FUNCCODE", "") + "',pkValue:'" + dynaBean.getStr("POSTIL_MODELID", "") + "',userId:'" + createUserId + "'});\">查看</a>!");
        Set<String> userIds = new HashSet<String>();
        if (StringUtil.isNotEmpty(hfrId)) {
            userIds.add(hfrId);
        }
        userIds.add(createUserId);
        for (String userId : userIds) {
            if (!currentUser.getUserId().equals(userId)) {
                List<UserMsgAppInfo> userMsgAppInfos = new ArrayList<>();
                net.sf.json.JSONObject params = new net.sf.json.JSONObject();
                params.put("pkValue", dynaBean.getStr("POSTIL_MODELID", ""));
                UserMsgAppInfo appInfo = new UserMsgAppInfo(dynaBean.getStr("POSTIL_FUNCNAME"), "APPFUNC", dynaBean.getStr("POSTIL_FUNCCODE", ""), "form", params);
                userMsgAppInfos.add(appInfo);
                pcMessageManager.sendDwr(userId, title, context.toString(), "JE.showMsg", "JE.showBatchMsg", true);
                pcMessageManager.sendUserMsg(userId, title, context.toString(), "PZ", userMsgAppInfos);
            }
        }

        return dynaBean;
    }

    public void readFuncEdit(MethodArgument param) {
        String tableCode = param.getTableCode();
        String funcCode = param.getFuncCode();
        String pkValue = param.getPkValue();
        EndUser currentUser = SecurityUserHolder.getCurrentUser();
        commonService.doDataFuncEdit(funcCode, tableCode, pkValue, currentUser.getUserId(), "0");
    }

    public JSONObject loadBadge(MethodArgument param) {

        //功能相关配置
        String funcCode = param.getFuncCode();
        String funcType = "func";
        String funcSql = "";
        if (StringUtils.isNotBlank(funcCode)) {
            //获取功能配置
            FuncInfo funcInfo = commonService.functionConfig(funcCode);
            funcType = funcInfo.getFuncType();
            funcSql = funcInfo.getSql();
        }

        //tableCode
        String tableCode = param.getTableCode();
        //构建条件
        ConditionsWrapper wrapper = buildWrapper(param);
        //查询条件sql 示例:  name=#{name} and (code=#{code} or id=#{id} )
        String whereSql = wrapper.getSql();
        //去除Order
        if (whereSql.toUpperCase().contains("ORDER BY")) {
            whereSql = whereSql.substring(0, whereSql.toUpperCase().indexOf("ORDER BY"));
        }
        //[{"field":"SY_AUDFLAG","codes":["NOSTATUS","WAIT","SUSPEND","ENDED"],"sm":"0","sql":""},{"field":"XSSJ_SJJB_CODE","codes":["0","1"],"sm":"0","sql":""},{"field":"XSSJ_JHLY_CODE","codes":["XSZH","ZHZY","TBGG","GGXC","DHZX","KHJS","GSZY","GRZY","WECHAT","QQ","QT"],"sm":"0","sql":""}]
        JSONArray items = JSONArray.parseArray(param.getStrData());
        //返回数据
        JSONObject result = new JSONObject();
        //存储过程不支持
        if (ArrayUtils.contains(new String[]{"procedure", "iditprocedure"}, funcType)) {
            return result;
        }
        //sql类型功能无tableCode  查询sql语句执行的结果
        if ("sql".equalsIgnoreCase(funcType)) {
            tableCode = " (" + funcSql + ") a ";
        }

        //遍历传参
        for (int i = 0; i < items.size(); i++) {
            JSONObject objs = items.getJSONObject(i);
            //字典对应的字段名
            String fieldCode = objs.getString("field");
            //字典项
            JSONArray codeVals = objs.getJSONArray("codes");
            // 弃用
            String sql = objs.getString("sql");
            //多选单选
            String sm = objs.getString("sm");
            //查询结果
            JSONObject valsInfo = new JSONObject();
            if (!"1".equals(sm)) {
                //单选
                //构建解析器
                ConditionsWrapper select_ = ConditionsWrapper.builder().apply("SELECT ").apply(fieldCode).apply(",COUNT(*) AS FIELDCOUNT from ").apply(tableCode)
                        .apply(StringUtils.isNotBlank(whereSql), " WHERE ").apply(StringUtils.isNotBlank(whereSql), whereSql)
                        .apply(" GROUP BY  ").apply(fieldCode);
                //加入参数
                select_.putAll(wrapper.getParameter());
                //指定表名
                select_.table(tableCode);
                //执行结果
                List<Map<String, Object>> countVals = metaService.selectSql(select_);
                for (Map<String, Object> valusInfo : countVals) {
                    if (StringUtil.isNotEmpty(valusInfo.get(fieldCode))) {
                        long count = Long.parseLong(StringUtil.getDefaultValue(valusInfo.get("FIELDCOUNT").toString(), "0"));
                        valsInfo.put(String.valueOf(valusInfo.get(fieldCode)), count);
                    }
                }
                for (int j = 0; j < codeVals.size(); j++) {
                    String code = codeVals.getString(j);
                    if (StringUtil.isNotEmpty(code) && !valsInfo.containsKey(code)) {
                        valsInfo.put(code, 0);
                    }
                }
            } else {
                //多选使用like
                for (int j = 0; j < codeVals.size(); j++) {
                    String val = codeVals.getString(j);
                    //构建解析器
                    ConditionsWrapper select_ = ConditionsWrapper.builder().apply("SELECT COUNT(*) from ").apply(tableCode)
                            .apply(" WHERE ").apply(whereSql)
                            .like(fieldCode, val);
                    //加入参数
                    select_.putAll(wrapper.getParameter());
                    long count = metaService.countBySql(select_);
                    valsInfo.put(val, count);
                }
            }
            result.put(fieldCode, valsInfo);
        }
        return result;
    }

    public void executeDataFlow(List<String> dataFlowIdList) {
        List<DynaBean> dataFlows = metaService.select("JE_CORE_DATAFLOW", ConditionsWrapper.builder().in("JE_CORE_DATAFLOW_ID", dataFlowIdList));
        for (DynaBean dataFlow : dataFlows) {
            String sql = dataFlow.getStr("DATAFLOW_SQL");
            if (StringUtils.isNotBlank(sql)) {
                metaService.executeSql(sql);
            }
        }
    }

    /**
     * 获取动态列的列规划数据
     *
     * @param param
     * @return
     */
    public void getIditProcedureColumn(MethodArgument param) {
        // TODO 获取动态列的列规划数据
    }

}
